import { useComDesignStoreWithOut } from '@/store'
import { ref, unref, computed, markRaw, watch, nextTick, shallowRef } from 'vue'

import {
  BwCustomComPropDataTypeEnum,
  BwComPropSetConstValueComEnum,
  BwCustomComNodeAttrFromTypeEnum as BwAttrFromTypeEnum,
  BwCustomComNodeAttrDataTypeEnum as BwAttrDataTypeEnum,
  type BwCustomComNodeAttrModel,
} from '@bitwit/base-com-render'

import type { BwCurNodeAttrInfoModel } from '../model'
import type { BwJsExtndInfoModel } from '../../../../coms/JSExtend/model'

import BwColSpan from './const/colSpan/index.vue'
import BwColorPicker from './const/colorPicker/index.vue'
import BwDataObjSelect from './const/dataObjSelect/index.vue'
import BwDataObjField from './const/dataObjField/index.vue'
import BwTableColumnConfig from './const/tableColumnConfig/index.vue'
import BwTableActionBars from './const/tableActionBars/index.vue'
import BwTableActionColumn from './const/tableActionColumn/index.vue'
import BwTableStatistic from './const/tableStatistic/index.vue'
import BwDataSourceConfig from './const/dataSource/index.vue'
import BwIconPicker from './const/iconPicker/index.vue'
import BwTabsItems from './const/tabsItems/index.vue'

export function useNodeAttrValue(props, emit) {
  const designStore = useComDesignStoreWithOut()

  const curConstEle = shallowRef<any>(null)
  const curVisible = ref<boolean>(false)
  const curConstValue = ref<any>('')
  const curComVarName = ref<string>('')
  const curComParamName = ref<string>('')
  const curJSExpression = ref<BwJsExtndInfoModel>({})
  const curConstEleProps = ref<Record<string, any>>({})
  const curConstEleEmits = ref<Record<string, Function>>({})

  const curConstEleBindProps = computed(() => {
    const attrInfo: BwCurNodeAttrInfoModel = props.attrInfo

    const options = unref(curConstEleProps)
    const com = attrInfo.constValueSetCom
    switch (com) {
      case BwComPropSetConstValueComEnum.input:
      case BwComPropSetConstValueComEnum.number:
      case BwComPropSetConstValueComEnum.select: {
        options.value = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.textarea: {
        const curValue = unref(curConstValue) ?? ''

        options.value =
          typeof curValue === 'string' ? curValue : JSON.stringify(curValue)
        break
      }
      case BwComPropSetConstValueComEnum.colSpan: {
        options.title = attrInfo.name
        options.value = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.switch: {
        options.checked = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.date: {
        options.value = unref(curConstValue)
      }
      case BwComPropSetConstValueComEnum.dateRange: {
        options.value = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.time: {
        options.value = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.color: {
        options.value = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.dataObjSelect: {
        options.value = unref(curConstValue)
        break
      }
      case BwComPropSetConstValueComEnum.dataObjField: {
        options.value = unref(curConstValue)
        options.dataObjId = props.attrData?.dataSourceDataObj?.constValue
        break
      }
      case BwComPropSetConstValueComEnum.tableColumnConfig: {
        options.value = unref(curConstValue)
        options.dataObjId = props.attrData?.dataSourceDataObj?.constValue
        break
      }
      case BwComPropSetConstValueComEnum.tableActionBars: {
        options.value = unref(curConstValue)
        options.dataObjId = props.attrData?.dataSourceDataObj?.constValue
        break
      }
      case BwComPropSetConstValueComEnum.tableActionColumn: {
        options.value = unref(curConstValue)
        options.dataObjId = props.attrData?.dataSourceDataObj?.constValue
        break
      }
      case BwComPropSetConstValueComEnum.tableStatistic: {
        options.value = unref(curConstValue)
        options.dataObjId = props.attrData?.dataSourceDataObj?.constValue
        break
      }
      case BwComPropSetConstValueComEnum.dataSourceConfig: {
        options.value = unref(curConstValue)
      }
      case BwComPropSetConstValueComEnum.icon: {
        options.value = unref(curConstValue)
      }
      case BwComPropSetConstValueComEnum.tabsItems: {
        options.value = unref(curConstValue)
        break
      }
    }

    return options
  })

  /** 当前自定义组件外放属性列表 */
  const curCurtomComPropList = computed(() => {
    const list: Array<Record<string, string>> = []
    const designInfo = designStore.curDesignInfo
    const comProps = designInfo?.comProps

    if (Array.isArray(comProps) && comProps.length) {
      comProps.forEach((item) => {
        list.push({ label: item.name ?? '', value: item.key })
      })
    }
    return list
  })

  /** 初始化常量值配置组件 */
  const initConstEle = (com?: BwComPropSetConstValueComEnum) => {
    switch (com) {
      case BwComPropSetConstValueComEnum.input: {
        curConstEle.value = 'AInput'
        break
      }
      case BwComPropSetConstValueComEnum.number: {
        curConstEle.value = 'AInputNumber'
        break
      }
      case BwComPropSetConstValueComEnum.switch: {
        curConstEle.value = 'ASwitch'
        break
      }
      case BwComPropSetConstValueComEnum.select: {
        curConstEle.value = 'ASelect'
        break
      }
      case BwComPropSetConstValueComEnum.textarea: {
        curConstEle.value = 'ATextarea'
        break
      }
      case BwComPropSetConstValueComEnum.colSpan: {
        curConstEle.value = markRaw(BwColSpan)
        break
      }
      case BwComPropSetConstValueComEnum.date: {
        curConstEle.value = 'ADatePicker'
        break
      }
      case BwComPropSetConstValueComEnum.dateRange: {
        curConstEle.value = 'ARangePicker'
        break
      }
      case BwComPropSetConstValueComEnum.time: {
        curConstEle.value = 'ATimePicker'
        break
      }
      case BwComPropSetConstValueComEnum.color: {
        curConstEle.value = markRaw(BwColorPicker)
        break
      }
      case BwComPropSetConstValueComEnum.dataObjSelect: {
        curConstEle.value = markRaw(BwDataObjSelect)
        break
      }
      case BwComPropSetConstValueComEnum.dataObjField: {
        curConstEle.value = markRaw(BwDataObjField)
        break
      }
      case BwComPropSetConstValueComEnum.tableColumnConfig: {
        curConstEle.value = markRaw(BwTableColumnConfig)
        break
      }
      case BwComPropSetConstValueComEnum.tableActionBars: {
        curConstEle.value = markRaw(BwTableActionBars)
        break
      }
      case BwComPropSetConstValueComEnum.tableActionColumn: {
        curConstEle.value = markRaw(BwTableActionColumn)
        break
      }
      case BwComPropSetConstValueComEnum.tableStatistic: {
        curConstEle.value = markRaw(BwTableStatistic)
        break
      }
      case BwComPropSetConstValueComEnum.dataSourceConfig: {
        curConstEle.value = markRaw(BwDataSourceConfig)
        break
      }
      case BwComPropSetConstValueComEnum.icon: {
        curConstEle.value = markRaw(BwIconPicker)
        break
      }
      case BwComPropSetConstValueComEnum.tabsItems: {
        curConstEle.value = markRaw(BwTabsItems)
        break
      }

      default: {
        curConstEle.value = 'ATextarea'
        break
      }
    }
  }
  /** 初始化常量值配置组件属性 */
  const initConstEleProps = (
    com?: BwComPropSetConstValueComEnum,
    props?: string
  ) => {
    curConstEleProps.value = {}
    try {
      const options = props ? JSON.parse(props) : {}
      switch (com) {
        case BwComPropSetConstValueComEnum.number: {
          options.style = `width: 100%`
          break
        }
        case BwComPropSetConstValueComEnum.select: {
          options.style = `width: 100%`
          options.value = unref(curConstValue)
          options.showSearch = true
          options.optionFilterProp = 'label'
          break
        }
        case BwComPropSetConstValueComEnum.switch: {
          options.checked = unref(curConstValue)
          break
        }
      }
      curConstEleProps.value = options
    } catch (error) {
      console.error(error)
    }
  }

  /** 初始化常量值配置组件事件 */
  const initConstEleEmits = (com?: BwComPropSetConstValueComEnum) => {
    const emits: Record<string, Function> = {}
    switch (com) {
      case BwComPropSetConstValueComEnum.input:
      case BwComPropSetConstValueComEnum.textarea: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.number: {
        emits['update:value'] = (value) => {
          const curValue = [undefined, null].includes(value)
            ? 'null'
            : value.toString()

          curConstValue.value = value
          onChangeAttrValue(curValue)
        }
        break
      }
      case BwComPropSetConstValueComEnum.select: {
        emits['update:value'] = (value) => {
          const curValue = Array.isArray(value)
            ? JSON.stringify(value)
            : value.toString()

          curConstValue.value = value
          onChangeAttrValue(curValue)
        }
        break
      }
      case BwComPropSetConstValueComEnum.switch: {
        emits['update:checked'] = (value) => {
          const curValue = [undefined, null].includes(value)
            ? 'null'
            : value.toString()

          curConstValue.value = value
          onChangeAttrValue(curValue)
        }
        break
      }
      case BwComPropSetConstValueComEnum.colSpan: {
        emits['update:value'] = (value) => {
          const curValue = [undefined, null].includes(value)
            ? 'null'
            : JSON.stringify(value)

          curConstValue.value = value
          onChangeAttrValue(curValue)
        }
        break
      }
      case BwComPropSetConstValueComEnum.date: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.dateRange: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.time: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.color: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.dataObjSelect: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.dataObjField: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.tableColumnConfig: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.tableActionBars: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.tableActionColumn: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
        break
      }
      case BwComPropSetConstValueComEnum.tableStatistic: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
      }
      case BwComPropSetConstValueComEnum.dataSourceConfig: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
      }
      case BwComPropSetConstValueComEnum.icon: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
      }
      case BwComPropSetConstValueComEnum.tabsItems: {
        emits['update:value'] = (value) => {
          curConstValue.value = value
          onChangeAttrValue(value)
        }
      }
    }
    curConstEleEmits.value = emits
  }

  const toDataTypeValue = (
    value: string,
    dataType?: BwCustomComPropDataTypeEnum | BwAttrDataTypeEnum
  ) => {
    switch (dataType) {
      case BwAttrDataTypeEnum.string:
      case BwCustomComPropDataTypeEnum.string: {
        return value
      }
      case BwAttrDataTypeEnum.boolean:
      case BwCustomComPropDataTypeEnum.boolean: {
        return ['true', true].includes(value) ? true : false
      }
      case BwAttrDataTypeEnum.number:
      case BwCustomComPropDataTypeEnum.number: {
        return ['null', 'undefined', ''].includes(value)
          ? undefined
          : Number(value)
      }
      case BwAttrDataTypeEnum.array:
      case BwCustomComPropDataTypeEnum.array: {
        if (Array.isArray(value)) {
          return value
        }
      }
      case BwAttrDataTypeEnum.object:
      case BwCustomComPropDataTypeEnum.object: {
        try {
          return value ? JSON.parse(value) : undefined
        } catch (error) {
          console.error(error)
          return undefined
        }
      }
      default: {
        return undefined
      }
    }
  }

  /** 初始化属性值 */
  const initAttrValue = (attrInfo: BwCurNodeAttrInfoModel) => {
    const curData: Record<string, BwCustomComNodeAttrModel> = props.attrData
    const name = attrInfo.key
    const curItem = curData[name ?? '']

    if (curItem) {
      const valueFrom = curItem.valueFromType
      switch (valueFrom) {
        case BwAttrFromTypeEnum.constValue: {
          if (curItem.constValue) {
            const dataType = curItem.valueDataType
            curConstValue.value = toDataTypeValue(curItem.constValue, dataType)
          } else {
            const deftValue = attrInfo.defaultValue ?? ''
            const dataType = attrInfo.defaultValueDataType
            curConstValue.value = toDataTypeValue(
              deftValue,
              dataType ?? undefined
            )
          }
          break
        }
        case BwAttrFromTypeEnum.comVar: {
          curComVarName.value = curItem.comVarName ?? ''
        }
        case BwAttrFromTypeEnum.comProps: {
          curComParamName.value = curItem.comPropsName ?? ''
        }
        case BwAttrFromTypeEnum.JSExpression: {
          curJSExpression.value = {
            logic: curItem.jsExpBodyLogic ?? undefined,
            params: curItem.jsExpParams ?? undefined,
          }
        }
      }
    } else {
      const deftValue = attrInfo.defaultValue ?? ''
      const dataType = attrInfo.defaultValueDataType

      curComVarName.value = ''
      curComParamName.value = ''
      curConstValue.value = toDataTypeValue(deftValue, dataType ?? undefined)
    }
  }

  /** 更新JS表达式 */
  const onChangeJSExpression = (data: BwJsExtndInfoModel) => {
    const curValue: Record<string, any> = {
      jsExpParams: data.params,
      jsExpBodyLogic: data.logic,
    }

    onChangeAttrValue(curValue)
  }
  /** 修改组件属性值 */
  const onChangeAttrValue = (value: any) => {
    const curAttrName = props?.attrInfo?.key ?? ''
    emit('change', curAttrName, value)
  }

  watch(
    () => props.attrInfo,
    (newVal?: BwCurNodeAttrInfoModel) => {
      if (newVal) {
        const com = newVal.constValueSetCom
        const comProps = newVal.constValueSetComProps

        initConstEle(com)
        initConstEleEmits(com)
        initAttrValue(newVal)
        initConstEleProps(com, comProps ?? undefined)
      } else {
        curConstEle.value = null
        curConstValue.value = ''
        curComVarName.value = ''
        curComParamName.value = ''
        curConstEleEmits.value = {}
      }
    },
    { deep: true, immediate: true }
  )

  watch(
    () => props.attrData,
    (newVal?: Record<string, BwCustomComNodeAttrModel>) => {
      if (newVal) {
        nextTick(() => {
          initAttrValue(props.attrInfo)
        })
      }
    },
    { deep: true, immediate: false }
  )

  return {
    curVisible,
    curConstEle,
    curConstValue,
    curComVarName,
    curComParamName,
    curJSExpression,
    curConstEleEmits,
    curConstEleBindProps,
    curCurtomComPropList,

    onChangeAttrValue,
    onChangeJSExpression,
  }
}
